from lib.funcs import *
from psutil import *
from threading import *
import time
import tkinter as tk


def exit_thread(thread):
    exctype = SystemExit
    import ctypes
    import inspect
    tid = ctypes.c_long(thread.ident)
    if not inspect.isclass(exctype):
        exctype = type(exctype)
    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(
        tid, ctypes.py_object(exctype))
    if res == 0:
        # raise ValueError("invalid thread id")
        pass
    elif res != 1:
        ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
        raise SystemError("PyThreadState_SetAsyncExc failed")


class sysm_class:
    def __init__(self, sittings):
        self.wait = time.sleep

        self.clock = time.perf_counter()

        self.cpu_count = cpu_count()
        self.sittings = sittings

        self.monitor = Thread(target=self.monitoring)
        self.monitor.start()

        self.wait(2)

    def monitoring(self):
        self._last_net = 0

        while True:
            self.get_data()
            self.process()

            self._last_net = self._net_io
            self.clock = time.time

    def get_data(self):
        self._memory = virtual_memory()
        self._swap = swap_memory()
        self._cpu_uses = cpu_percent(interval=True, percpu=True)
        self._net_io = net_io_counters()
        self.clock = time.perf_counter()
        self._boot_time = boot_time()

    def process(self):
        self.memo = f"{self.sittings['memory_format']%(self._memory.used/1024/1024)} MB : {self._memory.percent}%"
        self.swap = f"{self.sittings['memory_format']%(self._swap.used/1024/1024)} MB : {self._swap.percent}%"

        self.cpu = ""
        cpu_name = 1
        for each_cpu in self._cpu_uses:
            self.cpu += f"CPU{cpu_name}:{'{:.2f}%'.format(each_cpu)}\t"
            cpu_name += 1
            if cpu_name % 2 == 1:
                self.cpu += '\n'

        try:
            speed_down = (self._net_io.bytes_recv -
                          self._last_net.bytes_recv) / (time.perf_counter() - self.clock)
            speed_up = (self._net_io.bytes_sent -
                        self._last_net.bytes_sent) / (time.perf_counter() - self.clock)

            self.net_speed = f"Up:{self.sittings['netspeed_format']%(speed_up/1024/1024/1024)} MB/s\tDown:{self.sittings['netspeed_format']%(speed_down/1024/1024/1024)} MB/s"
        except AttributeError:
            self.net_speed = ""

    def __del__(self):
        exit_thread(self.monitor)


class GUI_sysm:
    '''图形界面管理类-sysm界面'''

    def __init__(self, father, sitting) -> None:
        '''初始化'''
        self.sitting = sitting["modules"]["sysm"]
        self.window = father

        self.__init__component()
        self.run = Thread(target=self.func_run)
        self.run.start()

    def __init__component(self):
        '''初始化组件'''

        self.func = sysm_class(self.sitting)  # 功能

        self.frame_cpu = tk.LabelFrame(self.window, text='CPU')
        self.cpu_textfield_data = tk.StringVar()
        self.cpu_textfield = tk.Label(
            self.frame_cpu, width=100, font=["Arial", 10], textvariable=self.cpu_textfield_data)
        self.cpu_textfield.pack(side=tk.TOP)
        self.frame_cpu.pack(side=tk.TOP)

        self.frame_mem = tk.LabelFrame(self.window, text="Memory")
        self.mem_textfield_data = tk.StringVar()
        self.mem_textfield = tk.Label(
            self.frame_mem, width=100, font=["Arial", 10], textvariable=self.mem_textfield_data)
        self.mem_textfield.pack(side=tk.TOP)
        self.frame_mem.pack(side=tk.TOP)

        self.frame_net = tk.LabelFrame(self.window, text='Net')
        self.net_textfield_data = tk.StringVar()
        self.net_textfield = tk.Label(
            self.frame_net, width=100, font=["Arial", 10], textvariable=self.net_textfield_data)
        self.net_textfield.pack(side=tk.TOP)
        # self.net_data = tk.Canvas()
        self.frame_net.pack(side=tk.TOP)

    def func_run(self):
        '''运行'''
        try:
            while True:
                self.cpu_textfield_data.set(self.func.cpu)
                self.mem_textfield_data.set('Memory: ' + self.func.memo + '\n' +
                                            'Swap: ' + self.func.swap)
                self.net_textfield_data.set(self.func.net_speed)
                self.func.wait(0.5)
        except RuntimeError:
            import sys
            sys.exit(0)

    def __del__(self):
        exit_thread(self.run)
        self.func.__del__()
